package flirtme.managers;

import java.util.Observable;

import flirtme.activities.MainMenuActivity;
import flirtme.activities.UserProfileActivity;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;

public class GPSManager extends Observable implements LocationListener
{	
	private static long MIN_UPDATE_TIME = 10 * 1000;
	private static float MIN_DISTANCE_CHANGE = 10;
	public static final int OUT_OF_SERVICE = 0;
	public static final int TEMPORARILY_UNAVAILABLE = 1;
	public static final int AVAILABLE = 2;
	
	private static GPSManager _instance = null;
	private static Location _currentLocation;
	private Activity _mainActivity;
	private Boolean _updatesActivated;
	
	private GPSManager()
	{
		_currentLocation = null;
		_updatesActivated = false;
	}
	
	public static GPSManager Instance()
	{
		if ( _instance == null )
			_instance = new GPSManager();
		return _instance;
	}
	
	public void requestGPSActivation(final LocationManager locationManager)
	{
		if ( !locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) )
		{
			AlertDialog.Builder builder = new AlertDialog.Builder(_mainActivity);
			
	        builder.setMessage("Please turn On the GPS to search for near devices.").setCancelable(false).setPositiveButton("Location Settings", new DialogInterface.OnClickListener() {
	            public void onClick(DialogInterface dialog, int id) {
	//            	startActivityForResult(new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS), 0);
	                Intent gpsOptionsIntent = new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS);
	                _mainActivity.startActivity(gpsOptionsIntent);
	                activateLocationRequests();
//	                requestGPSActivation(locationManager);
	            }
	        });
	        
	        builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
	            public void onClick(DialogInterface dialog, int id) {
	                dialog.cancel();
	        		Intent intent = new Intent(_mainActivity, UserProfileActivity.class);
	        		_mainActivity.startActivity(intent);
	            }
	        });
	        
	        AlertDialog alert = builder.create();
	        alert.show();
		}
		else
			activateLocationRequests();
			
	}

	public void startLocationReceiver( Activity mainactivity )//LocationManager locationManager)
	{
		_mainActivity = mainactivity;
		LocationManager locationManager = (LocationManager) _mainActivity.getSystemService(Context.LOCATION_SERVICE);
		
		// Request GPS activation before initializing updates
		this.requestGPSActivation(locationManager);
	}
	
	private void activateLocationRequests()
	{
		LocationManager locationManager = (LocationManager) _mainActivity.getSystemService(Context.LOCATION_SERVICE);
		String locationProvider = LocationManager.NETWORK_PROVIDER;
		locationManager.requestLocationUpdates(locationProvider, MIN_UPDATE_TIME, MIN_DISTANCE_CHANGE, GPSManager.Instance());
		locationProvider = LocationManager.GPS_PROVIDER;
		locationManager.requestLocationUpdates(locationProvider, MIN_UPDATE_TIME, MIN_DISTANCE_CHANGE, GPSManager.Instance());
		
		_updatesActivated = true;
	}
	
	public void stopLocationReceiver()
	{
		LocationManager locationManager = (LocationManager) _mainActivity.getSystemService(Context.LOCATION_SERVICE);
		locationManager.removeUpdates(this);
		
		_updatesActivated = false;
	}
	
	@Override
	public void onLocationChanged(Location location) 
	{
		if ( isBetterLocation(location, _currentLocation) )
		{
			_currentLocation = location;
			this.setChanged();
			this.notifyObservers(_currentLocation);
		}
	}

	@Override
	public void onProviderDisabled(String provider) {
//		if( provider.equals(LocationManager.GPS_PROVIDER) )
//		{
//			//Cuando se deshabilita el GPS promtear un msg
//			AlertDialog.Builder builder = new AlertDialog.Builder(_mainActivity);
//			
//	        builder.setMessage("Your GPS is disabled! Please turn on the GPS to search for near devices.").setCancelable(false).setPositiveButton("Enable GPS", new DialogInterface.OnClickListener() {
//	            public void onClick(DialogInterface dialog, int id) {
//	                Intent gpsOptionsIntent = new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS);
//	                _mainActivity.startActivity(gpsOptionsIntent);
//	            }
//	        });
//	        
//	        builder.setNegativeButton("Home Screen", new DialogInterface.OnClickListener() {
//	            public void onClick(DialogInterface dialog, int id) {
//	            	_instance.stopLocationReceiver();
//	                dialog.cancel();
//	                // Ir al home -> User Profile Activity
//	            }
//	        });
//	        
//	        AlertDialog alert = builder.create();
//	        alert.show();
//		}
		
	}

	@Override
	public void onProviderEnabled(String provider) {
//		if( !_updatesActivated && (provider.equals(LocationManager.GPS_PROVIDER)) )
//			startLocationReceiver(_mainActivity);
	}

	@Override
	public void onStatusChanged(String provider, int status, Bundle extras) 
	{
		// Condicion de cambio de un provedor de posicion
		switch (status)
		{
		case AVAILABLE:
			break;
		
		case TEMPORARILY_UNAVAILABLE:
			break;
			
		case OUT_OF_SERVICE:
			break;
			
		}
		
	}

	/** Determines whether one Location reading is better than the current Location fix
	  * @param location  The new Location that you want to evaluate
	  * @param currentBestLocation  The current Location fix, to which you want to compare the new one
	  */
	protected boolean isBetterLocation(Location location, Location currentBestLocation) {
	    if (currentBestLocation == null) {
	        // A new location is always better than no location
	        return true;
	    }

	    // Check whether the new location fix is newer or older
	    long timeDelta = location.getTime() - currentBestLocation.getTime();
	    boolean isSignificantlyNewer = timeDelta > 2*MIN_UPDATE_TIME;
	    boolean isSignificantlyOlder = timeDelta < -2*MIN_UPDATE_TIME;
	    boolean isNewer = timeDelta > 0;

	    // If it's been more than two minutes since the current location, use the new location
	    // because the user has likely moved
	    if (isSignificantlyNewer) {
	        return true;
	    // If the new location is more than two minutes older, it must be worse
	    } else if (isSignificantlyOlder) {
	        return false;
	    }

	    // Check whether the new location fix is more or less accurate
	    int accuracyDelta = (int) (location.getAccuracy() - currentBestLocation.getAccuracy());
	    boolean isLessAccurate = accuracyDelta > 0;
	    boolean isMoreAccurate = accuracyDelta < 0;
	    boolean isSignificantlyLessAccurate = accuracyDelta > 200;

	    // Check if the old and new location are from the same provider
	    boolean isFromSameProvider = isSameProvider(location.getProvider(),
	            currentBestLocation.getProvider());

	    // Determine location quality using a combination of timeliness and accuracy
	    if (isMoreAccurate) {
	        return true;
	    } else if (isNewer && !isLessAccurate) {
	        return true;
	    } else if (isNewer && !isSignificantlyLessAccurate && isFromSameProvider) {
	        return true;
	    }
	    return false;
	}

	/** Checks whether two providers are the same */
	private boolean isSameProvider(String provider1, String provider2) {
	    if (provider1 == null) {
	      return provider2 == null;
	    }
	    return provider1.equals(provider2);
	}
	
	public Location getCurrentLocation()
	{
		return _currentLocation;
	}

	
}
